/* Copyright 2009 Sony Mathew, Minneapolis MN. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at  http://www.apache.org/licenses/LICENSE-2.0  Unless required by applicable law or agreed to in writing, software  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */
package com.xsm.gwt.widgets.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.xsm.lite.util.Debuggable;
import com.xsm.lite.util.StringUtil;

/**
 * @author Sony Mathew
 */
public class GWTUtil {

    private static String BASE_URL = null;
    
	/**
	 * The "clear()" method doesn't actually remove
	 * the <tr> and <td> values from the table.
	 * If you want to resize, or add different styles,
	 * you need to call clearTable first.
	 */
	public static void clearTable(FlexTable table) {
		int rows = table.getRowCount();
		for (int i = 0; i < rows; i++) {
			table.removeRow(0);
		}
	}
	
    /**
     * If it starts with "/" then treats it like a relative URL to the context-root
     *  of the application and prefixes the base url (upto context-root) 
     *  otherwise treats it like a full url (not relative to anything).
     *  
     * @see #toFullURL(String)
     * 
     * @return String : the normalized URL - a complete URL string.
     * 
     * author Sony Mathew
     */
    public static String normalizeURL(String url) {
        if ((url=url.trim()).startsWith("/")) {
            url = GWTUtil.toFullURL(url);
        }
        return url;
    }
    
    /**
     * Given a URL relative to the context-root will tack on the base URL to 
     *  form a complete URL String.
     *  
     * @param contextRootRelativeURL : Must start with '/' to indicate a  
     *  URL relative to the application context-root.
     * 
     * @see #getBaseURL()
     * 
     * author Sony Mathew
     */
    public static String toFullURL(String contextRootRelativeURL) {
        return getBaseURL() + contextRootRelativeURL;        
    }
    
    /**
     * Obtain the base url in the form: http://my.domain:port/my-context-root/ 
     *  from GWT.getModuleBaseURL().
     *  
     * @see #getBaseURL(String)
     * 
     * author Sony Mathew
     */
    public static String getBaseURL() {
        if (BASE_URL == null) {
            BASE_URL = getBaseURL(GWT.getModuleBaseURL());
        }
        return BASE_URL;
    }
    
    /**
     * Obtain the base url upto http://my.domain:port/my-context-root 
     *  from a known URL that represents some content.
     *  
     * author Sony Mathew
     */
    public static String getBaseURL(String knownURL) {
        String errorMsg = "Unexpected URL [" + knownURL + "], cannot extract base URL";
        
        if (knownURL == null || (knownURL=knownURL.trim()).length() == 0) {
            throw new IllegalStateException(errorMsg);
        }

        int slashIndex = 0;
        for(int i=0;i<4;i++) {
            slashIndex = knownURL.indexOf('/', slashIndex);
            if (slashIndex < 0) {
                throw new IllegalStateException(errorMsg);
            }
            slashIndex++; 
        }
        
        return knownURL.substring(0, slashIndex-1);        
    }
    
    /**
     * Sets the size of the given widget in pixels.
     * 
     * author Sony Mathew
     */
    public static void setPixelSize(Widget w, double pxWidth, double pxHeight) {
        w.setSize(((int)pxWidth) + "px", ((int)pxHeight) + "px");
    }
    
    /**
     * Sets and Id on the given Widget.
     * 
     * author Sony Mathew
     */
    public static void setId(Widget w, String id) {
        DOM.setElementAttribute(w.getElement(), "id", id);
    }
    
    /**
     * A utility to check if an element is visible currently.
     * 
     * author Sony Mathew
     */
    public static native boolean isVisible(Element e) /*-{
        var isVisible = function(obj) {
            if (obj == $doc) return true
            
            if (!obj) return false
            
            if (!obj.parentNode) return false
            
            if (obj.style) {
                if (obj.style.display == 'none') return false
                if (obj.style.visibility == 'hidden') return false
            }
            
            //Try the computed style in a standard way
            if (window.getComputedStyle) {
                var style = window.getComputedStyle(obj, "")
                if (style.display == 'none') return false
                if (style.visibility == 'hidden') return false
            }
            
            //Or get the computed style using IE's silly proprietary way
            var style = obj.currentStyle
            if (style) {
                if (style['display'] == 'none') return false
                if (style['visibility'] == 'hidden') return false
            }
            
            return isVisible(obj.parentNode);
      }
      
      return isVisible(e);
    }-*/;

    /**
     * Provide a convenient debug string for a widget.
     * 
     * author Sony Mathew
     */
    public static String toDebugString(Object w) {
        if (w == null) {
            return "null";            
        }
        if (w instanceof Debuggable) {
            return ((Debuggable)w).toDebugString();
        }else if (w instanceof Widget) {
            return w.getClass().getName();
        }else{
            return StringUtil.toString(w);
        }
    }

    /**
     * Creates a new horizintal line.
     */
    public static Widget horizontalLine() {
        SimplePanel horizontalLine = new SimplePanel();
        horizontalLine.addStyleName("horizontal-line");
        return horizontalLine;
    }

    /**
     * Creates a new space.
     */
    public static Widget space() {
        return space(1);
    }
    
    /**
     * Creates a new space repeated as many times as requested.
     */
    public static Widget space(int repeat) {
        /*
        SimplePanel spc = new SimplePanel();
        spc.addStyleName("space");
        return spc;
        */
        return new HTML(StringUtil.repeat("&nbsp;", repeat));
    }

    /**
     * Creates a new space with a vertical line separator.
     * 
     * author Sony Mathew
     */
    public static Widget spaceVerticalLineGrey() {
        return new CSSPanel().css("verticalLineTextSeparatorGrey").wrap(space());
    }

    /**
     * Creates a new space with a vertical line separator.
     * 
     * author Sony Mathew
     */
    public static Widget spaceVerticalLineWhite() {
        return new CSSPanel().css("verticalLineTextSeparatorWhite").wrap(space());
    }
    
    /**
     * Create a label that is styled bold (and default font).
     * 
     * author Sony Mathew
     */
    public static Label boldLabel(String text) {
        Label label = new Label(text, false);
        label.addStyleName("bold-label");
        return label;
    }

    /**
     * Create a label that is styled as a word with right padding.
     * 
     * author Sony Mathew
     */
    public static Label wordLabel(String text) {
        Label label = new Label(text, false);
        label.addStyleName("word-label");
        return label;
    }

    /**
     * Styles a label that is a word with right padding.
     * 
     * author Sony Mathew
     */
    public static Label wordLabel(Label label) {
        label.addStyleName("word-label");
        return label;
    }

    /**
     * Create a panel with multiple lines of labels that are styled bold (and default font).
     * Each text passed is placed on its own line.
     * 
     * author Sony Mathew
     */    
    public static Widget multiLineBoldLabel(String... texts) {
        VerticalPanel vp = new VerticalPanel();
        for(String text : texts) {
            vp.add(boldLabel(text));
        }        
        return vp;
    }

    /**
     * Creats an HTML widget from the given text.
     * Will also translate all spaces into &nbsp;
     * 
     * author Sony Mathew
     */
    public static HTML toHtml(String text) {
        StringBuffer htmlText = new StringBuffer();
        for(int i=0;i<text.length();i++) {
            char c = text.charAt(i);
            if (c == ' ') {
                htmlText.append("&nbsp;");
            }else{
                htmlText.append(c);
            }
        }
        HTML html = new HTML(htmlText.toString());
        return html;
    }
}
